home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gxtype1.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  19.1 KB  |  670 lines

  1. /* Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gxtype1.c,v 1.6.2.1 2000/10/07 16:59:12 rayjj Exp $ */
  20. /* Adobe Type 1 font interpreter support */
  21. #include "math_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsccode.h"
  25. #include "gsline.h"
  26. #include "gsstruct.h"
  27. #include "gxarith.h"
  28. #include "gxchrout.h"
  29. #include "gxfixed.h"
  30. #include "gxistate.h"
  31. #include "gxmatrix.h"
  32. #include "gxcoord.h"
  33. #include "gxfont.h"
  34. #include "gxfont1.h"
  35. #include "gxtype1.h"
  36. #include "gzpath.h"
  37.  
  38. /*
  39.  * The routines in this file are used for both Type 1 and Type 2
  40.  * charstring interpreters.
  41.  */
  42.  
  43. /*
  44.  * Define whether or not to force hints to "big pixel" boundaries
  45.  * when rasterizing at higher resolution.  With the current algorithms,
  46.  * a value of 1 is better for devices without alpha capability,
  47.  * but 0 is better if alpha is available.
  48.  */
  49. #define FORCE_HINTS_TO_BIG_PIXELS 1
  50.  
  51. /* Structure descriptor */
  52. public_st_gs_font_type1();
  53.  
  54. /* Define the structure type for a Type 1 interpreter state. */
  55. public_st_gs_type1_state();
  56. /* GC procedures */
  57. private 
  58. ENUM_PTRS_WITH(gs_type1_state_enum_ptrs, gs_type1_state *pcis)
  59. {
  60.     if (index < pcis->ips_count + 4) {
  61.     ENUM_RETURN_CONST_STRING_PTR(gs_type1_state,
  62.                      ipstack[index - 4].char_string);
  63.     }
  64.     return 0;
  65. }
  66. ENUM_PTR3(0, gs_type1_state, pfont, pis, path);
  67. ENUM_PTR(3, gs_type1_state, callback_data);
  68. ENUM_PTRS_END
  69. private RELOC_PTRS_WITH(gs_type1_state_reloc_ptrs, gs_type1_state *pcis)
  70. {
  71.     int i;
  72.  
  73.     RELOC_PTR(gs_type1_state, pfont);
  74.     RELOC_PTR(gs_type1_state, pis);
  75.     RELOC_PTR(gs_type1_state, path);
  76.     RELOC_PTR(gs_type1_state, callback_data);
  77.     for (i = 0; i < pcis->ips_count; i++) {
  78.     ip_state *ipsp = &pcis->ipstack[i];
  79.     int diff = ipsp->ip - ipsp->char_string.data;
  80.  
  81.     RELOC_CONST_STRING_VAR(ipsp->char_string);
  82.     ipsp->ip = ipsp->char_string.data + diff;
  83.     }
  84. } RELOC_PTRS_END
  85.  
  86. /* ------ Interpreter services ------ */
  87.  
  88. #define s (*ps)
  89.  
  90. /* We export this for the Type 2 charstring interpreter. */
  91. void
  92. accum_xy_proc(register is_ptr ps, fixed dx, fixed dy)
  93. {
  94.     ptx += c_fixed(dx, xx),
  95.     pty += c_fixed(dy, yy);
  96.     if (sfc.skewed)
  97.     ptx += c_fixed(dy, yx),
  98.         pty += c_fixed(dx, xy);
  99. }
  100.  
  101. /* Initialize a Type 1 interpreter. */
  102. /* The caller must supply a string to the first call of gs_type1_interpret. */
  103. int
  104. gs_type1_interp_init(register gs_type1_state * pcis, gs_imager_state * pis,
  105.     gx_path * ppath, const gs_log2_scale_point * pscale, bool charpath_flag,
  106.              int paint_type, gs_font_type1 * pfont)
  107. {
  108.     static const gs_log2_scale_point no_scale = {0, 0};
  109.     const gs_log2_scale_point *plog2_scale =
  110.     (FORCE_HINTS_TO_BIG_PIXELS ? pscale : &no_scale);
  111.  
  112.     pcis->pfont = pfont;
  113.     pcis->pis = pis;
  114.     pcis->path = ppath;
  115.     pcis->callback_data = pfont; /* default callback data */
  116.     /*
  117.      * charpath_flag controls coordinate rounding, hinting, and
  118.      * flatness enhancement.  If we allow it to be set to true,
  119.      * charpath may produce results quite different from show.
  120.      */
  121.     pcis->charpath_flag = false /*charpath_flag */ ;
  122.     pcis->paint_type = paint_type;
  123.     pcis->os_count = 0;
  124.     pcis->ips_count = 1;
  125.     pcis->ipstack[0].ip = 0;
  126.     pcis->ipstack[0].char_string.data = 0;
  127.     pcis->ipstack[0].char_string.size = 0;
  128.     pcis->ignore_pops = 0;
  129.     pcis->init_done = -1;
  130.     pcis->sb_set = false;
  131.     pcis->width_set = false;
  132.     pcis->have_hintmask = false;
  133.     pcis->num_hints = 0;
  134.     pcis->seac_accent = -1;
  135.  
  136.     /* Set the sampling scale. */
  137.     set_pixel_scale(&pcis->scale.x, plog2_scale->x);
  138.     set_pixel_scale(&pcis->scale.y, plog2_scale->y);
  139.  
  140.     return 0;
  141. }
  142.  
  143. /* Set the push/pop callback data. */
  144. void
  145. gs_type1_set_callback_data(gs_type1_state *pcis, void *callback_data)
  146. {
  147.     pcis->callback_data = callback_data;
  148. }
  149.  
  150.  
  151. /* Preset the left side bearing and/or width. */
  152. void
  153. gs_type1_set_lsb(gs_type1_state * pcis, const gs_point * psbpt)
  154. {
  155.     pcis->lsb.x = float2fixed(psbpt->x);
  156.     pcis->lsb.y = float2fixed(psbpt->y);
  157.     pcis->sb_set = true;
  158. }
  159. void
  160. gs_type1_set_width(gs_type1_state * pcis, const gs_point * pwpt)
  161. {
  162.     pcis->width.x = float2fixed(pwpt->x);
  163.     pcis->width.y = float2fixed(pwpt->y);
  164.     pcis->width_set = true;
  165. }
  166.  
  167. /* Finish initializing the interpreter if we are actually rasterizing */
  168. /* the character, as opposed to just computing the side bearing and width. */
  169. void
  170. gs_type1_finish_init(gs_type1_state * pcis, gs_op1_state * ps)
  171. {
  172.     gs_imager_state *pis = pcis->pis;
  173.  
  174.     /* Set up the fixed version of the transformation. */
  175.     gx_matrix_to_fixed_coeff(&ctm_only(pis), &pcis->fc, max_coeff_bits);
  176.     sfc = pcis->fc;
  177.  
  178.     /* Set the current point of the path to the origin, */
  179.     /* in anticipation of the initial [h]sbw. */
  180.     {
  181.     gx_path *ppath = pcis->path;
  182.  
  183.     ptx = pcis->origin.x = ppath->position.x;
  184.     pty = pcis->origin.y = ppath->position.y;
  185.     }
  186.  
  187.     /* Initialize hint-related scalars. */
  188.     pcis->asb_diff = pcis->adxy.x = pcis->adxy.y = 0;
  189.     pcis->flex_count = flex_max;    /* not in Flex */
  190.     pcis->dotsection_flag = dotsection_out;
  191.     pcis->vstem3_set = false;
  192.     pcis->vs_offset.x = pcis->vs_offset.y = 0;
  193.     pcis->hints_initial = 0;    /* probably not needed */
  194.     pcis->hint_next = 0;
  195.     pcis->hints_pending = 0;
  196.  
  197.     /* Assimilate the hints proper. */
  198.     {
  199.     gs_log2_scale_point log2_scale;
  200.  
  201.     log2_scale.x = pcis->scale.x.log2_unit;
  202.     log2_scale.y = pcis->scale.y.log2_unit;
  203.     if (pcis->charpath_flag)
  204.         reset_font_hints(&pcis->fh, &log2_scale);
  205.     else
  206.         compute_font_hints(&pcis->fh, &pis->ctm, &log2_scale,
  207.                    &pcis->pfont->data);
  208.     }
  209.     reset_stem_hints(pcis);
  210.  
  211.     /* Compute the flatness needed for accurate rendering. */
  212.     pcis->flatness = gs_char_flatness(pis, 0.001);
  213.  
  214.     /* Move to the side bearing point. */
  215.     accum_xy(pcis->lsb.x, pcis->lsb.y);
  216.     pcis->position.x = ptx;
  217.     pcis->position.y = pty;
  218.  
  219.     pcis->init_done = 1;
  220. }
  221.  
  222. /* ------ Operator procedures ------ */
  223.  
  224. int
  225. gs_op1_closepath(register is_ptr ps)
  226. {                /* Note that this does NOT reset the current point! */
  227.     gx_path *ppath = sppath;
  228.     subpath *psub;
  229.     segment *pseg;
  230.     fixed dx, dy;
  231.     int code;
  232.  
  233.     /* Check for and suppress a microscopic closing line. */
  234.     if ((psub = ppath->current_subpath) != 0 &&
  235.     (pseg = psub->last) != 0 &&
  236.     (dx = pseg->pt.x - psub->pt.x,
  237.      any_abs(dx) < float2fixed(0.1)) &&
  238.     (dy = pseg->pt.y - psub->pt.y,
  239.      any_abs(dy) < float2fixed(0.1))
  240.     )
  241.     switch (pseg->type) {
  242.         case s_line:
  243.         code = gx_path_pop_close_subpath(sppath);
  244.         break;
  245.         case s_curve:
  246.         /*
  247.          * Unfortunately, there is no "s_curve_close".  (Maybe there
  248.          * should be?)  Just adjust the final point of the curve so it
  249.          * is identical to the closing point.
  250.          */
  251.         pseg->pt = psub->pt;
  252. #define pcseg ((curve_segment *)pseg)
  253.         pcseg->p2.x -= dx;
  254.         pcseg->p2.y -= dy;
  255. #undef pcseg
  256.         /* falls through */
  257.         default:
  258.         /* What else could it be?? */
  259.         code = gx_path_close_subpath(sppath);
  260.     } else
  261.     code = gx_path_close_subpath(sppath);
  262.     if (code < 0)
  263.     return code;
  264.     return gx_path_add_point(ppath, ptx, pty);    /* put the point where it was */
  265. }
  266.  
  267. int
  268. gs_op1_rrcurveto(register is_ptr ps, fixed dx1, fixed dy1,
  269.          fixed dx2, fixed dy2, fixed dx3, fixed dy3)
  270. {
  271.     gs_fixed_point pt1, pt2;
  272.     fixed ax0 = sppath->position.x - ptx;
  273.     fixed ay0 = sppath->position.y - pty;
  274.  
  275.     accum_xy(dx1, dy1);
  276.     pt1.x = ptx + ax0, pt1.y = pty + ay0;
  277.     accum_xy(dx2, dy2);
  278.     pt2.x = ptx, pt2.y = pty;
  279.     accum_xy(dx3, dy3);
  280.     return gx_path_add_curve(sppath, pt1.x, pt1.y, pt2.x, pt2.y, ptx, pty);
  281. }
  282.  
  283. #undef s
  284.  
  285. /* Record the side bearing and character width. */
  286. int
  287. gs_type1_sbw(gs_type1_state * pcis, fixed lsbx, fixed lsby, fixed wx, fixed wy)
  288. {
  289.     if (!pcis->sb_set)
  290.     pcis->lsb.x = lsbx, pcis->lsb.y = lsby,
  291.         pcis->sb_set = true;    /* needed for accented chars */
  292.     if (!pcis->width_set)
  293.     pcis->width.x = wx, pcis->width.y = wy,
  294.         pcis->width_set = true;
  295.     if_debug4('1', "[1]sb=(%g,%g) w=(%g,%g)\n",
  296.           fixed2float(pcis->lsb.x), fixed2float(pcis->lsb.y),
  297.           fixed2float(pcis->width.x), fixed2float(pcis->width.y));
  298.     return 0;
  299. }
  300.  
  301. /* Blend values for a Multiple Master font instance. */
  302. /* The stack holds values ... K*N othersubr#. */
  303. int
  304. gs_type1_blend(gs_type1_state *pcis, fixed *csp, int num_results)
  305. {
  306.     gs_type1_data *pdata = &pcis->pfont->data;
  307.     int num_values = fixed2int_var(csp[-1]);
  308.     int k1 = num_values / num_results - 1;
  309.     int i, j;
  310.     fixed *base;
  311.     fixed *deltas;
  312.  
  313.     if (num_values < num_results ||
  314.     num_values % num_results != 0
  315.     )
  316.     return_error(gs_error_invalidfont);
  317.     base = csp - 1 - num_values;
  318.     deltas = base + num_results - 1;
  319.     for (j = 0; j < num_results;
  320.      j++, base++, deltas += k1
  321.      )
  322.     for (i = 1; i <= k1; i++)
  323.         *base += deltas[i] *
  324.         pdata->WeightVector.values[i];
  325.     pcis->ignore_pops = num_results;
  326.     return num_values - num_results + 2;
  327. }
  328.  
  329. /*
  330.  * Handle a seac.  Do the base character now; when it finishes (detected
  331.  * in endchar), do the accent.  Note that we pass only 4 operands on the
  332.  * stack, and pass asb separately.
  333.  */
  334. int
  335. gs_type1_seac(gs_type1_state * pcis, const fixed * cstack, fixed asb,
  336.           ip_state * ipsp)
  337. {
  338.     gs_font_type1 *pfont = pcis->pfont;
  339.     gs_const_string bcstr;
  340.     int code;
  341.  
  342.     /* Save away all the operands. */
  343.     pcis->seac_accent = fixed2int_var(cstack[3]);
  344.     pcis->save_asb = asb;
  345.     pcis->save_lsb = pcis->lsb;
  346.     pcis->save_adxy.x = cstack[0];
  347.     pcis->save_adxy.y = cstack[1];
  348.     pcis->os_count = 0;        /* clear */
  349.     /* Ask the caller to provide the base character's CharString. */
  350.     code = (*pfont->data.procs.seac_data)
  351.     (pfont, fixed2int_var(cstack[2]), NULL, &bcstr);
  352.     if (code != 0)
  353.     return code;
  354.     /* Continue with the supplied string. */
  355.     ipsp->char_string = bcstr;
  356.     return 0;
  357. }
  358.  
  359. /*
  360.  * Handle the end of a character.  Return 0 if this is really the end of a
  361.  * character, or 1 if we still have to process the accent of a seac.
  362.  * In the latter case, the interpreter control stack has been set up to
  363.  * point to the start of the accent's CharString; the caller must
  364.  * also set ptx/y to pcis->position.x/y.
  365.  */
  366. int
  367. gs_type1_endchar(gs_type1_state * pcis)
  368. {
  369.     gs_imager_state *pis = pcis->pis;
  370.     gx_path *ppath = pcis->path;
  371.  
  372.     if (pcis->seac_accent >= 0) {    /* We just finished the base character of a seac. */
  373.     /* Do the accent. */
  374.     gs_font_type1 *pfont = pcis->pfont;
  375.     gs_op1_state s;
  376.     gs_const_string astr;
  377.     int achar = pcis->seac_accent;
  378.     int code;
  379.  
  380.     pcis->seac_accent = -1;
  381.     /* Reset the coordinate system origin */
  382.     sfc = pcis->fc;
  383.     ptx = pcis->origin.x, pty = pcis->origin.y;
  384.     pcis->asb_diff = pcis->save_asb - pcis->save_lsb.x;
  385.     pcis->adxy = pcis->save_adxy;
  386.     /*
  387.      * We're going to add in the lsb of the accented character
  388.      * (*not* the lsb of the accent) when we encounter the
  389.      * [h]sbw of the accent, so ignore the lsb for now.
  390.      */
  391.     accum_xy(pcis->adxy.x, pcis->adxy.y);
  392.     ppath->position.x = pcis->position.x = ptx;
  393.     ppath->position.y = pcis->position.y = pty;
  394.     pcis->os_count = 0;    /* clear */
  395.     /* Clear the ipstack, in case the base character */
  396.     /* ended inside a subroutine. */
  397.     pcis->ips_count = 1;
  398.     /* Remove any base character hints. */
  399.     reset_stem_hints(pcis);
  400.     /* Ask the caller to provide the accent's CharString. */
  401.     code = (*pfont->data.procs.seac_data)(pfont, achar, NULL, &astr);
  402.     if (code < 0)
  403.         return code;
  404.     /* Continue with the supplied string. */
  405.     pcis->ips_count = 1;
  406.     pcis->ipstack[0].char_string = astr;
  407.     return 1;
  408.     }
  409.     if (pcis->hint_next != 0 || path_is_drawing(ppath))
  410.     apply_path_hints(pcis, true);
  411.     /* Set the current point to the character origin */
  412.     /* plus the width. */
  413.     {
  414.     gs_fixed_point pt;
  415.  
  416.     gs_point_transform2fixed(&pis->ctm,
  417.                  fixed2float(pcis->width.x),
  418.                  fixed2float(pcis->width.y),
  419.                  &pt);
  420.     gx_path_add_point(ppath, pt.x, pt.y);
  421.     }
  422.     if (pcis->scale.x.log2_unit + pcis->scale.y.log2_unit == 0) {    /*
  423.                                      * Tweak up the fill adjustment.  This is a hack for when
  424.                                      * we can't oversample.  The values here are based entirely
  425.                                      * on experience, not theory, and are designed primarily
  426.                                      * for displays and low-resolution fax.
  427.                                      */
  428.     gs_fixed_rect bbox;
  429.     int dx, dy, dmax;
  430.  
  431.     gx_path_bbox(ppath, &bbox);
  432.     dx = fixed2int_ceiling(bbox.q.x - bbox.p.x);
  433.     dy = fixed2int_ceiling(bbox.q.y - bbox.p.y);
  434.     dmax = max(dx, dy);
  435.     if (pcis->fh.snap_h.count || pcis->fh.snap_v.count ||
  436.         pcis->fh.a_zone_count
  437.         ) {            /* We have hints.  Only tweak up a little at */
  438.         /* very small sizes, to help nearly-vertical */
  439.         /* or nearly-horizontal diagonals. */
  440.         pis->fill_adjust.x = pis->fill_adjust.y =
  441.         (dmax < 15 ? float2fixed(0.15) :
  442.          dmax < 25 ? float2fixed(0.1) :
  443.          fixed_0);
  444.     } else {        /* No hints.  Tweak a little more to compensate */
  445.         /* for lack of snapping to pixel grid. */
  446.         pis->fill_adjust.x = pis->fill_adjust.y =
  447.         (dmax < 10 ? float2fixed(0.2) :
  448.          dmax < 25 ? float2fixed(0.1) :
  449.          float2fixed(0.05));
  450.     }
  451.     } else {            /* Don't do any adjusting. */
  452.     pis->fill_adjust.x = pis->fill_adjust.y = fixed_0;
  453.     }
  454.     /* Set the flatness for curve rendering. */
  455.     if (!pcis->charpath_flag)
  456.     gs_imager_setflat(pis, pcis->flatness);
  457.     return 0;
  458. }
  459.  
  460. /* ------ Font procedures ------ */
  461.  
  462. int
  463. gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
  464.             int members, gs_glyph_info_t *info)
  465. {
  466.     gs_font_type1 *const pfont = (gs_font_type1 *)font;
  467.     gs_type1_data *const pdata = &pfont->data;
  468.     int wmode = pfont->WMode;
  469.     int piece_members = members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
  470.     int width_members = members & (GLYPH_INFO_WIDTH0 << wmode);
  471.     int default_members = members - (piece_members + width_members);
  472.     int code = 0;
  473.     gs_const_string str;
  474.  
  475.     if (default_members) {
  476.     code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
  477.  
  478.     if (code < 0)
  479.         return code;
  480.     } else
  481.     info->members = 0;
  482.  
  483.     if (default_members != members) {
  484.     if ((code = pdata->procs.glyph_data(pfont, glyph, &str)) < 0)
  485.         return code;        /* non-existent glyph */
  486.     }
  487.  
  488.     if (piece_members) {
  489.     gs_glyph *pieces =
  490.         (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
  491.     /*
  492.      * Decode the CharString looking for seac.  We have to process
  493.      * callsubr, callothersubr, and return operators, but if we see
  494.      * any other operators other than [h]sbw, pop, hint operators,
  495.      * or endchar, we can return immediately.  We have to include
  496.      * endchar because it is an (undocumented) equivalent for seac
  497.      * in Type 2 CharStrings: see the cx_endchar case in
  498.      * gs_type2_interpret in gstype2.c.
  499.      *
  500.      * It's really unfortunate that we have to duplicate so much parsing
  501.      * code, but factoring out the parser from the interpreter would
  502.      * involve more restructuring than we're prepared to do right now.
  503.      */
  504.     bool encrypted = pdata->lenIV >= 0;
  505.     fixed cstack[ostack_size];
  506.     fixed *csp;
  507.     ip_state ipstack[ipstack_size + 1];
  508.     ip_state *ipsp = &ipstack[0];
  509.     const byte *cip;
  510.     crypt_state state;
  511.     int c;
  512.     
  513.     CLEAR_CSTACK(cstack, csp);
  514.     info->num_pieces = 0;    /* default */
  515.     cip = str.data;
  516.     call:
  517.     state = crypt_charstring_seed;
  518.     if (encrypted) {
  519.         int skip = pdata->lenIV;
  520.  
  521.         /* Skip initial random bytes */
  522.         for (; skip > 0; ++cip, --skip)
  523.         decrypt_skip_next(*cip, state);
  524.     }
  525.     top:
  526.     for (;;) {
  527.         uint c0 = *cip++;
  528.  
  529.         charstring_next(c0, state, c, encrypted);
  530.         if (c >= c_num1) {
  531.         /* This is a number, decode it and push it on the stack. */
  532.         if (c < c_pos2_0) {    /* 1-byte number */
  533.             decode_push_num1(csp, c);
  534.         } else if (c < cx_num4) {    /* 2-byte number */
  535.             decode_push_num2(csp, c, cip, state, encrypted);
  536.         } else if (c == cx_num4) {    /* 4-byte number */
  537.             long lw;
  538.  
  539.             decode_num4(lw, cip, state, encrypted);
  540.             *++csp = int2fixed(lw);
  541.         } else        /* not possible */
  542.             return_error(gs_error_invalidfont);
  543.         continue;
  544.         }
  545. #define cnext CLEAR_CSTACK(cstack, csp); goto top
  546.         switch ((char_command) c) {
  547.         default:
  548.         goto out;
  549.         case c_callsubr:
  550.         c = fixed2int_var(*csp);
  551.         code = pdata->procs.subr_data
  552.             (pfont, c, false, &ipsp[1].char_string);
  553.         if (code < 0)
  554.             return_error(code);
  555.         --csp;
  556.         ipsp->ip = cip, ipsp->dstate = state;
  557.         ++ipsp;
  558.         cip = ipsp->char_string.data;
  559.         goto call;
  560.         case c_return:
  561.         --ipsp;
  562.         cip = ipsp->ip, state = ipsp->dstate;
  563.         goto top;
  564.         case cx_hstem:
  565.         case cx_vstem:
  566.         case c1_hsbw:
  567.         cnext;
  568.         case cx_endchar:
  569.         if (csp < cstack + 3)
  570.             goto out;    /* not seac */
  571.         do_seac:
  572.         /* This is the payoff for all this code! */
  573.         if (pieces) {
  574.             gs_char bchar = fixed2int(csp[-1]);
  575.             gs_char achar = fixed2int(csp[0]);
  576.             int bcode =
  577.             pdata->procs.seac_data(pfont, bchar,
  578.                            &pieces[0], NULL);
  579.             int acode =
  580.             pdata->procs.seac_data(pfont, achar,
  581.                            &pieces[1], NULL);
  582.  
  583.             code = (bcode < 0 ? bcode : acode);
  584.         }
  585.         info->num_pieces = 2;
  586.         goto out;
  587.         case cx_escape:
  588.         charstring_next(*cip, state, c, encrypted);
  589.         ++cip;
  590.         switch ((char1_extended_command) c) {
  591.         default:
  592.             goto out;
  593.         case ce1_vstem3:
  594.         case ce1_hstem3:
  595.         case ce1_sbw:
  596.             cnext;
  597.         case ce1_pop:
  598.             /*
  599.              * pop must do nothing, since it is used after
  600.              * subr# 1 3 callothersubr.
  601.              */
  602.             goto top;
  603.         case ce1_seac:
  604.             goto do_seac;
  605.         case ce1_callothersubr:
  606.             switch (fixed2int_var(*csp)) {
  607.             default:
  608.             goto out;
  609.             case 3:
  610.             csp -= 2;
  611.             goto top;
  612.             case 12:
  613.             case 13:
  614.             case 14:
  615.             case 15:
  616.             case 16:
  617.             case 17:
  618.             case 18:
  619.             cnext;
  620.             }
  621.         }
  622.         }
  623. #undef cnext
  624.     }
  625. out:    info->members |= piece_members;
  626.     }
  627.  
  628.     if (width_members) {
  629.     /*
  630.      * Interpret the CharString until we get to the [h]sbw.
  631.      */
  632.     gs_imager_state gis;
  633.     gs_type1_state cis;
  634.     static const gs_log2_scale_point no_scale = {0, 0};
  635.     int value;
  636.  
  637.     /* Initialize just enough of the imager state. */
  638.     if (pmat)
  639.         gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
  640.     else {
  641.         gs_matrix imat;
  642.  
  643.         gs_make_identity(&imat);
  644.         gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
  645.     }
  646.     gis.flatness = 0;
  647.     code = gs_type1_interp_init(&cis, &gis, NULL /* no path needed */,
  648.                     &no_scale, true, 0, pfont);
  649.     if (code < 0)
  650.         return code;
  651.     cis.charpath_flag = true;    /* suppress hinting */
  652.     code = pdata->interpret(&cis, &str, &value);
  653.     switch (code) {
  654.     case 0:        /* done with no [h]sbw, error */
  655.         code = gs_note_error(gs_error_invalidfont);
  656.     default:        /* code < 0, error */
  657.         return code;
  658.     case type1_result_callothersubr:    /* unknown OtherSubr */
  659.         return_error(gs_error_rangecheck); /* can't handle it */
  660.     case type1_result_sbw:
  661.         info->width[wmode].x = fixed2float(cis.width.x);
  662.         info->width[wmode].y = fixed2float(cis.width.y);
  663.         break;
  664.     }
  665.     info->members |= width_members;
  666.     }
  667.  
  668.     return code;
  669. }
  670.